package com.rem.concurrency.juc.my13Single;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * DCL 懒汉式
 * 反射 创建多个对象 加锁拦截
 * 只要一创建对象就直接通过反射创建,不走默认get方法 也会出现创建多个实例的情况
 * <p>
 * 加标志红绿灯来解决 还是可以通过反编译查看 然后通过反射破坏
 *
 * @author Rem
 * @date 2021-03-10
 */

public class LazyMan5 {


    /**
     * volatile 避免指定重排
     */
    private volatile static LazyMan5 lazyMan;


    private static boolean flag = false;

    /**
     * 构造加锁
     */
    private LazyMan5() {
        synchronized (LazyMan5.class) {
            if (flag == false) {
                flag = true;
            } else {
                throw new RuntimeException("不要试图通过反射创建单例");
            }
        }
        System.out.println(Thread.currentThread().getName() + "ok");
    }


    /**
     * 双层检测的锁模式 DCL懒汉式
     *
     * @return
     */
    public static LazyMan5 getLazyMan() {
        //加锁操作
        if (lazyMan == null) {
            //加锁
            synchronized (LazyMan5.class) {
                if (lazyMan == null) {
                    //不是一个原子性的操作
                    lazyMan = new LazyMan5();
                }
            }
        }
        return lazyMan;
    }

    public static void main(String[] args) throws Exception {
        Class<LazyMan5> aClass = LazyMan5.class;

        //破坏字段
        Field field = aClass.getDeclaredField("flag");
        field.setAccessible(true);

        //破坏构造
        Constructor<LazyMan5> declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);

        LazyMan5 lazyManA = declaredConstructor.newInstance();
        field.set(lazyManA, false);
        LazyMan5 lazyManB = declaredConstructor.newInstance();


        System.out.println(lazyManA);
        System.out.println(lazyManB);
        //false 只要一创建对象就直接通过反射创建,不走默认get方法 也会出现创建多个实例的情况
        System.out.println(lazyManB == lazyManA);

    }
}